#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
主题: 内存映射的二进制文件
问题: 你想内存映射一个二进制文件到一个可变字节数组中，目的可能是为了随机访问它的内容或者是原地做些修改。
提示 :
"""

import os
import mmap

filename = '10_memery_mapping.bin'


def recipe1():
    # 初始创建一个文件并将其内容扩充到指定大小

    size = 1000000
    with open(filename, 'wb') as f:
        f.seek(size - 1)
        f.write(b'\x00')

    m = memory_map(filename)
    print(f"{len(m) = }")
    print(f"{m[0:10] = }")
    print(f"{m[0] = }")
    m[0:11] = b'Hello World'
    m.close()

    # Verify that changes were made
    with open(filename, 'rb') as f:
        print(f"{f.read(20) = }")


def recipe2():
    '''上下文管理器'''
    with memory_map(filename) as m:
        print(f"{len(m) = }") 

def recipe3():
    '''内存视图来解析其中的数据'''
    m = memory_map(filename)
    # Memoryview of unsigned integers
    v = memoryview(m).cast('I')
    v[0] = 7
    print(f"{m[0:4] = }")
    m[0:4] = b'\x07\x01\x00\x00'
    print(f"{v[0] = }")

def memory_map(filename, access=mmap.ACCESS_WRITE):
    '''
    ACCESS_READ: 只读
    ACCESS_COPY: 复制
    '''
    size = os.path.getsize(filename)
    fd = os.open(filename, os.O_RDWR)
    return mmap.mmap(fd, size, access=access)

def main():
    print('recipe1'.center(20, '*'))
    recipe1()
    print('recipe2'.center(20, '*'))
    recipe2()
    print('recipe3'.center(20, '*'))
    recipe3()

if __name__ == '__main__':
    main()
